<?php
class ModulePaymentSina extends ModulePayment
{

    const PAYMENT_STATUS_DECLINE    = 3;
    const PAYMENT_STATUS_REFUND     = 4;
    const PAYMENT_STATUS_CHARGEBACK = 5;
    const PAYMENT_STATUS_DISPUTE    = 6;

    /**
     * @var ModuleSnsSina
     */
    private $moduleSns;

    /**
     * @see ModulePayment::__construct()
     */
    public function __construct($userId, $platform)
    {
        parent::__construct($userId, $platform);
        $this->moduleSns = ModuleSnsFactory::init(null, ModuleSnsConst::PFSA);
    }

    /**
     * @see ModulePayment::completeOrder()
     *
     * @return string | array(
     *  int $userId,
     *  ModulePaymentOrderVo $order
     *  array $paymentSetting
     * )
     */
    public function completeOrder()
    {
        /**
         * array(
         *      'SPID' => 'sina',
         *      'ServerID' => '0',
         *      'UserID' => '2146731414',
         *      'UserIP' => '0.0.0.0',
         *      'RoleID' => '366566',
         *      'OrderID' => 'XXXXX', // 新浪业务订单号：订单号唯一
         *      'GamePoint' => '200', // 平台通过PayPoint*充值比率计算得到的玩家本次充值可获得的游戏货币数量
         *      'PayPoint' => '1', // 充值对应的V币点数
         *      'Sign' => '003669fe5d67bbf3b3653345e618cd55',
         * )
         */
        $decodedInput = SzParam::getWholeRequest();

        // check the decoded structure
        if (!(
            isset($decodedInput['SPID'])
            && isset($decodedInput['ServerID'])
            && isset($decodedInput['UserID'])
            && isset($decodedInput['UserIP'])
            && isset($decodedInput['RoleID'])
            && isset($decodedInput['OrderID'])
            && isset($decodedInput['GamePoint'])
            && isset($decodedInput['PayPoint'])
            && isset($decodedInput['Sign'])
        )) {
            return 200;
        }

        // 更新返回值
        $return['ServerID'] = $decodedInput['ServerID'];
        $return['UserID']   = $decodedInput['UserID'];
        $return['RoleID']   = $decodedInput['RoleID'];

        // 获取appToken
        $appToken = $this->moduleSns->loadSnsSetting('appToken');
        
        // signature 验证
        if ($decodedInput['Sign'] != md5("SPID={$decodedInput['SPID']}&ServerID={$decodedInput['ServerID']}&UserID={$decodedInput['UserID']}&UserIP={$decodedInput['UserIP']}&RoleID={$decodedInput['RoleID']}&OrderID={$decodedInput['OrderID']}&GamePoint={$decodedInput['GamePoint']}&PayPoint={$decodedInput['PayPoint']}&key={$appToken['value']}")) {
            return 210;
        }

        // 游戏角色未创建
        $platformId = $decodedInput['UserID'];
        $userId = $this->moduleSns->portPlayerUserId($platformId);
        $profile = SzPersister::get()->getVo($userId, ModuleProfileConst::ORM_NAME_PROFILE);
        if (is_null($profile)) {
            return 213;
        }

        // 服务器维护，暂停服务
        $appConfig = SzConfig::get()->loadAppConfig('app');
        if ($appConfig['MAINTENANCE']) {
            return 217;
        }

        // 根据GamePoint数量匹配充值项目，如果未找到，则匹配充值单价
        $isUnitPrice = true; // 是否充值项目为“单价项目”
        $paymentSetting = null;
        $paymentSettings = SzConfig::get()->loadAppConfig(ModulePaymentConst::CONFIG_PAYMENT, null, true);
        foreach ($paymentSettings as $defaultPaymentSetting) {
            // 新浪平台仅支持付费购买MONEY
            if ($defaultPaymentSetting['type'] != ModulePaymentConst::PAYMENT_TYPE_MONEY) {
                continue;
            }

            // 充值项目数量完全匹配，直接获取当前充值项目配置
            if ($defaultPaymentSetting['amount'] == $decodedInput['GamePoint']) {
                $isUnitPrice = false;
                $paymentSetting = $defaultPaymentSetting;
                break;
            }

            // 充值项目可能不存在，获取零散充值项目，即充值单价
            if ($defaultPaymentSetting['amount'] == 1) {
                $paymentSetting = $defaultPaymentSetting;
            }
        }

        // 未找到付费项
        if (is_null($paymentSetting)) {
            return 217;
        }

        /**
         * @var ModulePaymentOrderVoList $orderList
         * @var ModulePaymentOrderVo $order
         */
        $orderList = SzPersister::get()->getVoList(null, ModulePaymentConst::ORM_NAME_PAYMENT_ORDER, $userId);
        foreach ($orderList->getList() as $order) {
            if ($order->getPlatformToken() == $decodedInput['OrderID']) {
                return 216;
            }
        }

        // 未充值过，全新订单创建
        $order = $this->createOrder($userId, $paymentSetting, $decodedInput['OrderID'], array(), true);

        // 计算充值数量与付费价格
        $quantity = ($isUnitPrice) ? $decodedInput['GamePoint'] : 1;
        $paymentPrice = $paymentSetting['price'] * $quantity;

        $order = $this->completeOrderAndSupplyResources($userId, $order, $paymentSetting, $quantity);
        $order->setPrice($paymentPrice);
        $orderList->updateElement($order->getOrderId(), $order);
        SzPersister::get()->setVoList($orderList);
        SzLogger::get()->debug('[ModulePaymentSina] Realtime update: payment completed normally');

        return array($userId, $order, $paymentSetting);
    }

    /**
     * @see ModulePayment::completeOrderReturnValue()
     */
    public function completeOrderReturnValue($result)
    {
        // 返回结构
        $return = array(
            'Code' => 0,
            'ErrorMsg' => '',
            'ServerID' => '',
            'UserID' => '',
            'RoleID' => '',
            'GameOrderID' => ''
        );

        if (is_array($result)) {
            /**
             * @var ModulePaymentOrderVo $order
             */
            list(, $order) = $result;
            $decodedInput = SzParam::getWholeRequest();
            $return['ServerID']     = $decodedInput['ServerID'];
            $return['UserID']       = $decodedInput['UserID'];
            $return['RoleID']       = $decodedInput['RoleID'];
            $return['GameOrderID']  = $order->getOrderId();
            return json_encode($return);
        } else {
            $return['Code'] = $result;
            return json_encode($return);
        }
    }

    /**
     * @see ModulePayment::repairOrder()
     */
    public function repairOrder($userId, $orderInfo)
    {
    }
}